﻿using SL651Center2.x.Enums;
using System.Text;
using System.Text.RegularExpressions;
using TouchSocket.Core;

namespace SL651Center2.x.Messages
{
    /// <summary>
    /// 要素数据
    /// </summary>
    public class MessageElement : IMessage
    {
        /// <summary>
        /// 流水号
        /// </summary>
        public byte[] SerialNumber { get; set; } = Array.Empty<byte>();
        /// <summary>
        /// 流水号数字形式
        /// </summary>
        public ushort SerialNum { get; set; }
        /// <summary>
        /// 发报时间
        /// </summary>
        public byte[] SendTime { get; set; } = Array.Empty<byte>();
        /// <summary>
        /// 发报时间字符串形式
        /// </summary>
        public string SendTimeStr { get; set; } = string.Empty;
        /// <summary>
        /// 遥测站地址
        /// </summary>
        public byte[] TelemetryAddress { get; set; } = Array.Empty<byte>();
        /// <summary>
        /// 遥测站地址的字符串形式
        /// </summary>
        public string TelemetryAddressStr { get; set; } = string.Empty;
        /// <summary>
        /// 遥测站分类码
        /// </summary>
        public TelemetryStationCode TelemetryStation { get; set; }
        /// <summary>
        /// 观测时间
        /// </summary>
        public byte[] ObservationTime { get; set; } = Array.Empty<byte>();
        /// <summary>
        /// 观测时间字符串
        /// </summary>
        public string ObservationTimeStr { get; set; } = string.Empty;

        /// <summary>
        /// 时段数据
        /// </summary>
        public TimeData[] TimeDatas { get; private set; } = Array.Empty<TimeData>();

        /// <summary>
        /// 数据列表
        /// </summary>
        public ElementData[] ElementDatas { get; private set; } = Array.Empty<ElementData>();

        public void Read(in ByteBlock byteBlock)
        {
            //流水号
            SerialNumber=byteBlock.ReadToSpan(2).ToArray();
            SerialNum = Convert.ToUInt16(Helper.ToHEXString(SerialNumber), 16);

            //发报时间
            SendTime = byteBlock.ReadToSpan(6).ToArray();
            SendTimeStr = Helper.ByteToBCDTime(SendTime);

            //遥测站地址
            _ = byteBlock.ReadByte();
            byteBlock.ReadByte();
            TelemetryAddress = byteBlock.ReadToSpan(5).ToArray();
            TelemetryAddressStr = Helper.ToHEXString(TelemetryAddress);

            //遥测站分类码
            TelemetryStation = (TelemetryStationCode)byteBlock.ReadByte();

            //观测时间
            var tt = byteBlock.ReadByte();
            byteBlock.Seek(1, SeekOrigin.Current);
            ObservationTime = byteBlock.ReadToSpan(5).ToArray();
            ObservationTimeStr = Helper.ByteToBCDTime(ObservationTime);

            List<ElementData> elements = new List<ElementData>();
            List<TimeData> datas = new List<TimeData>();

            //读取一个标识符
            var elemCode = byteBlock.ReadByte();
            while (elemCode != 0x03 && elemCode != 0x17)
            {
                //跳过数据定义
                //byteBlock.Seek(1, SeekOrigin.Current);
                //读取数据定义
                var dlen = byteBlock.ReadByte();
                var dalen = dlen >> 3;
                var dalen1 = dlen & 0x07;

                var (d, pre) = ElementInfo.GetValueType((ElementCode)elemCode);
                var (name, unit) = ElementInfo.Instance.GetInfo((ElementCode)elemCode);

                if (d != 0)
                {
                    var db = new byte[d];
                    byteBlock.Read(db);
                    var d1 = Helper.ToHEXString(db);
                    var num1 = Helper.HEXToBCDInt(d1);
                    decimal value;
                    if (Regex.IsMatch(d1, "^[Ff]*$"))
                    {
                        value = 0;
                    }
                    else if (pre != 0)
                    {
                        value = num1 / pre;
                    }
                    else
                    {
                        value = Convert.ToDecimal(num1);
                    }
                    ElementData data = new ElementData()
                    {
                        Code = (ElementCode)elemCode,
                        Name = name,
                        Unit = unit,
                        Value = value,
                    };
                    elements.Add(data);

                }
                else
                {
                    switch ((ElementCode)elemCode)
                    {
                        //1小时内每5分钟时段降雨量
                        case ElementCode.DRP:
                            {
                                //var d1 = Helper.ToHEXString(byteBlock.ReadToArray(12));
                                decimal[] value = new decimal[12];
                                Console.WriteLine(name);
                                for (int i = 0; i < 12; i++)
                                {
                                    decimal v = Convert.ToDecimal(byteBlock.ReadByte()) / 10;
                                    value[i] = v;
                                    Console.WriteLine($"{v}{unit}");
                                }
                                TimeData timeData = new TimeData()
                                {
                                    Code = (ElementCode)elemCode,
                                    Name = name,
                                    Unit = unit,
                                    Value = value,
                                };
                                datas.Add(timeData);
                                break;
                            }
                        case ElementCode.DRZ1:
                        case ElementCode.DRZ2:
                        case ElementCode.DRZ3:
                        case ElementCode.DRZ4:
                        case ElementCode.DRZ5:
                        case ElementCode.DRZ6:
                        case ElementCode.DRZ7:
                        case ElementCode.DRZ8:
                            {
                                //var d2 = Helper.ToHEXString(byteBlock.ReadToArray(24));
                                decimal[] value1 = new decimal[12];
                                Console.WriteLine(name);
                                for (int i = 0; i < 12; i++)
                                {
                                    decimal v = Convert.ToDecimal(byteBlock.ReadUInt16(EndianType.Big)) / 100;
                                    value1[i] = v;
                                    Console.WriteLine(v);
                                }
                                TimeData timeData = new TimeData()
                                {
                                    Code = (ElementCode)elemCode,
                                    Name = name,
                                    Unit = unit,
                                    Value = value1,
                                };
                                datas.Add(timeData);
                                break;
                            }
                        default:
                            break;
                    }
                }

                //读取下一个要素标识符
                elemCode = byteBlock.ReadByte();

            }

            ElementDatas = elements.ToArray();
            TimeDatas = datas.ToArray();

        }

        public void ReadASCII(in ByteBlock byteBlock)
        {
            //流水号
            SerialNumber = byteBlock.ReadToSpan(4).ToArray();
            SerialNum = Convert.ToUInt16(SerialNumber.ToASCIIString(), 16);

            //发报时间
            SendTime = byteBlock.ReadToSpan(12).ToArray();
            SendTimeStr = Helper.StringToBCDTime(SendTime.ToASCIIString());

            var datab = byteBlock.ToArray(byteBlock.Position);
            var datastr = datab.ToASCIIString();
            var arr = datastr.Split(" ");

            //遥测站地址
            TelemetryAddressStr = arr[1];
            TelemetryAddress = Encoding.ASCII.GetBytes(TelemetryAddressStr);

            //遥测站分类码
            var typestr = arr[2];
            if (Enum.IsDefined(typeof(TelemetryStationCode), typestr))
            {
                var typecode = (TelemetryStationCode)Enum.Parse(typeof(TelemetryStationCode), typestr);
                TelemetryStation = typecode;
            }


            List<ElementData> elements = new List<ElementData>();
            List<TimeData> datas = new List<TimeData>();

            for (int i = 3; i < arr.Length - 1; i += 2)
            {
                //观测时间
                if (arr[i] == "TT")
                {
                    var time = arr[i + 1];
                    ObservationTime = Encoding.ASCII.GetBytes(time);
                    ObservationTimeStr = Helper.StringToBCDTime(time);
                    continue;
                }

                if (arr[i] == "DRP")
                {
                    var elementCode = (ElementCode)Enum.Parse(typeof(ElementCode), arr[i]);
                    var (name, unit) = ElementInfo.Instance.GetInfo(arr[i]);

                    decimal[] value = new decimal[12];
                    for (int j = 0; j < 12; j++)
                    {
                        var d1 = arr[i + 1];
                        var v = Convert.ToDecimal(Convert.ToUInt16(d1, 16)) / 10;
                        if (Regex.IsMatch(d1, "^[Ff]*$"))
                        {
                            v = 0;
                        }
                        value[j] = v;

                        if (j < 11)
                        {
                            i += 1;
                        }
                    }
                    TimeData timeData = new TimeData()
                    {
                        Code = elementCode,
                        Name = name,
                        Unit = unit,
                        Value = value,
                    };
                    datas.Add(timeData);
                    continue;
                }

                if (arr[i].StartsWith("DRZ"))
                {
                    var elementCode = (ElementCode)Enum.Parse(typeof(ElementCode), arr[i]);
                    var (name, unit) = ElementInfo.Instance.GetInfo(arr[i]);
                    decimal[] value = new decimal[12];

                    for (int j = 0; j < 12; j++)
                    {
                        var d1 = arr[i + 1];
                        var v = Convert.ToDecimal(Convert.ToUInt16(d1, 16)) / 100;
                        if (Regex.IsMatch(d1, "^[Ff]*$"))
                        {
                            v = 0;
                        }
                        value[j] = v;
                        if (j < 11)
                        {
                            i += 1;
                        }
                    }
                    TimeData timeData = new TimeData()
                    {
                        Code = elementCode,
                        Name = name,
                        Unit = unit,
                        Value = value,
                    };
                    datas.Add(timeData);
                    continue;
                }

                if (Enum.IsDefined(typeof(ElementCode), arr[i]))
                {
                    var elementCode = (ElementCode)Enum.Parse(typeof(ElementCode), arr[i]);
                    var (name, unit) = ElementInfo.Instance.GetInfo(arr[i]);

                    var value = Convert.ToDecimal(arr[i + 1]);
                    ElementData data = new ElementData()
                    {
                        Code = elementCode,
                        Name = name,
                        Unit = unit,
                        Value = value,
                    };
                    elements.Add(data);
                }

            }

            ElementDatas = elements.ToArray();
            TimeDatas = datas.ToArray();

        }

    }
}
